#include "query_builder.h"
#include "kwdb_client.h"
#include "exceptions.h"

#include <sstream>
#include <algorithm>

namespace kwdb {

QueryBuilder::QueryBuilder(KWDBClient& client)
    : client_(client)
    , limitValue_(-1)
    , offsetValue_(-1) {
}

QueryBuilder& QueryBuilder::select(const std::vector<std::string>& columns) {
    selectColumns_ = columns;
    return *this;
}

QueryBuilder& QueryBuilder::select(const std::string& column) {
    selectColumns_ = {column};
    return *this;
}

QueryBuilder& QueryBuilder::from(const std::string& table) {
    fromTable_ = table;
    return *this;
}

QueryBuilder& QueryBuilder::where(const std::string& condition) {
    whereConditions_.clear();
    whereConditions_.push_back(condition);
    return *this;
}

QueryBuilder& QueryBuilder::andWhere(const std::string& condition) {
    whereConditions_.push_back("AND " + condition);
    return *this;
}

QueryBuilder& QueryBuilder::orWhere(const std::string& condition) {
    whereConditions_.push_back("OR " + condition);
    return *this;
}

QueryBuilder& QueryBuilder::orderBy(const std::string& column, const std::string& direction) {
    orderByClauses_.emplace_back(column, direction);
    return *this;
}

QueryBuilder& QueryBuilder::limit(int limit) {
    limitValue_ = limit;
    return *this;
}

QueryBuilder& QueryBuilder::offset(int offset) {
    offsetValue_ = offset;
    return *this;
}

QueryBuilder& QueryBuilder::param(const std::string& key, const std::string& value) {
    parameters_[key] = value;
    return *this;
}

QueryResult QueryBuilder::execute() {
    try {
        std::string sql = toSql();
        return client_.query(sql);
    } catch (const std::exception& e) {
        throw QueryException("查询执行失败: " + std::string(e.what()));
    }
}

std::future<QueryResult> QueryBuilder::executeAsync() {
    return std::async(std::launch::async, [this]() {
        return execute();
    });
}

std::string QueryBuilder::toSql() const {
    std::stringstream sql;
    
    // SELECT子句
    sql << "SELECT ";
    if (selectColumns_.empty()) {
        sql << "*";
    } else {
        for (size_t i = 0; i < selectColumns_.size(); ++i) {
            if (i > 0) {
                sql << ", ";
            }
            sql << escapeSqlString(selectColumns_[i]);
        }
    }
    
    // FROM子句
    if (!fromTable_.empty()) {
        sql << " FROM " << escapeSqlString(fromTable_);
    }
    
    // WHERE子句
    std::string whereClause = buildWhereClause();
    if (!whereClause.empty()) {
        sql << " WHERE " << whereClause;
    }
    
    // ORDER BY子句
    std::string orderByClause = buildOrderByClause();
    if (!orderByClause.empty()) {
        sql << " ORDER BY " << orderByClause;
    }
    
    // LIMIT子句
    std::string limitClause = buildLimitClause();
    if (!limitClause.empty()) {
        sql << " " << limitClause;
    }
    
    return sql.str();
}

QueryBuilder& QueryBuilder::reset() {
    selectColumns_.clear();
    fromTable_.clear();
    whereConditions_.clear();
    orderByClauses_.clear();
    limitValue_ = -1;
    offsetValue_ = -1;
    parameters_.clear();
    return *this;
}

std::string QueryBuilder::buildWhereClause() const {
    if (whereConditions_.empty()) {
        return "";
    }
    
    std::stringstream where;
    for (size_t i = 0; i < whereConditions_.size(); ++i) {
        if (i > 0) {
            where << " ";
        }
        where << whereConditions_[i];
    }
    
    return where.str();
}

std::string QueryBuilder::buildOrderByClause() const {
    if (orderByClauses_.empty()) {
        return "";
    }
    
    std::stringstream orderBy;
    for (size_t i = 0; i < orderByClauses_.size(); ++i) {
        if (i > 0) {
            orderBy << ", ";
        }
        orderBy << escapeSqlString(orderByClauses_[i].first) 
                << " " << orderByClauses_[i].second;
    }
    
    return orderBy.str();
}

std::string QueryBuilder::buildLimitClause() const {
    std::stringstream limit;
    
    if (limitValue_ > 0) {
        limit << "LIMIT " << limitValue_;
        
        if (offsetValue_ > 0) {
            limit << " OFFSET " << offsetValue_;
        }
    }
    
    return limit.str();
}

std::string QueryBuilder::escapeSqlString(const std::string& str) const {
    std::string result = str;
    
    // 转义单引号
    size_t pos = 0;
    while ((pos = result.find("'", pos)) != std::string::npos) {
        result.replace(pos, 1, "''");
        pos += 2;
    }
    
    // 如果包含空格或特殊字符，用反引号包围
    if (result.find(' ') != std::string::npos || 
        result.find('-') != std::string::npos ||
        result.find('.') != std::string::npos) {
        result = "`" + result + "`";
    }
    
    return result;
}

} // namespace kwdb
